﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace GEPSCodeTemplate
{
    public class Parser
    {
        private string _content;
        private string _result;
        private Dictionary<string, Param> _params;
        private Dictionary<string, string> _optionals;
        private const string ParamRegExpr = Param.ParamStartFlag + "{0}" 
            + Param.ParamSpliter + "([^" + Param.ParamSpliter + "])*"
            + Param.ParamSpliter + "([^" + Param.ParamSpliter + "])*"
            + Param.ParamEndFlag;
        private const string OptionalRegExpr = Param.OptionalStartFlag + "([^" + Param.OptionalEndFlag 
            + "])*" + Param.OptionalEndFlag;

        public string Result
        {
            get { return _result; }
        }

        public string Content
        {
            get { return _content; }
        }

        public Dictionary<string, Param> Params
        {
            get { return _params; }
        }

        public Dictionary<string, string> Optionals
        {
            get { return _optionals; }
        }

        public Parser(string Content)
        {
            _content = Content;
            _result = Content;
            _params = new Dictionary<string, Param>();
            _optionals = new Dictionary<string, string>();
            BuildParams();
        }

        public void UpdateParam(string name, string value)
        {
            if (_params.ContainsKey(name))
            {
                Param oParam;
                oParam.Name = _params[name].Name;
                oParam.Value = value;
                oParam.Descripe = _params[name].Descripe;
                _params[name] = oParam;
            }
        }

        public void BuildParams()
        {
            MatchCollection matchs = Regex.Matches(Content, string.Format(ParamRegExpr, "([^" + Param.ParamSpliter + "])*"));
            foreach (Match match in matchs)
            {
                string strParam = match.ToString();
                strParam = strParam.Substring(Param.ParamStartFlag.Length,
                    strParam.Length - Param.ParamStartFlag.Length - Param.ParamEndFlag.Length);
                string[] arrParam = strParam.Split(new string[]{Param.ParamSpliter}, StringSplitOptions.None);
                if (!_params.ContainsKey(arrParam[0]))
                {
                    Param oParam;
                    oParam.Name = arrParam[0];
                    oParam.Descripe = arrParam[1];
                    oParam.Value = arrParam[2];
                    _params.Add(arrParam[0], oParam);
                }
            }
        }

        public bool ReplaceAllParams()
        {
            _result = _content;
            foreach (string key in _params.Keys)
            {
                ReplaceParam(key);
            }
            return true;
        }

        public bool ReplaceParam(string Name)
        {
            if (!_params.ContainsKey(Name))
                return false;
            _result = Regex.Replace(_result, string.Format(ParamRegExpr, Name), _params[Name].Value);
            return true;
        }

        private void InitOptionals()
        {
            //int nStartPos = _content.IndexOf(Param.OptionalStartFlag, 0);
            //while (nStartPos >= 0)
            //{
            //    int nEndPos = _content.IndexOf(Param.OptionalEndFlag, nStartPos + 1);
            //    int nTempStartPos = _content.IndexOf(Param.OptionalStartFlag, nStartPos + 1);
            //    if ((nEndPos == -1) || ((nTempStartPos != -1) && (nEndPos > nTempStartPos)))
            //    {
            //        throw new Exception("文档格式有误");
            //    }
            //    string strOptional = _content.Substring(nStartPos + Param.OptionalStartFlag.Length,
            //        nEndPos - nStartPos - Param.OptionalStartFlag.Length);
            //    string[] arrOptional = strOptional.Split(',');
            //    Debug.Assert(arrOptional.Count() == 2);
            //    if (!_optionals.ContainsKey(arrOptional[0]))
            //        _optionals.Add(arrOptional[0], arrOptional[1]);
            //    nStartPos = nTempStartPos;
            //}
        }

        public bool SetOptional(string Name, bool Exclude)
        {
            if (!_optionals.ContainsKey(Name))
                return false;
            string strRegExpr = string.Format(ParamRegExpr, Name);
            var test = Regex.Matches(_result, strRegExpr);
            if (Exclude)
                _result = Regex.Replace(_result, strRegExpr, "");
            else
                _result = Regex.Replace(_result, strRegExpr, _optionals[Name]);
            return true;
        }
    }
}
